const { Service } = require('egg');
const { v4: uuidV4 } = require('uuid');
const moment = require('moment');
const axios = require('axios');
const { sm4 } = require('sm-crypto');

const history_table = 'request_history',
  user_table = 'user';
const table_name = 'permission';
class HomeService extends Service {

  async init() {
    const knex = this.app.knex;
    try {
      const list = [];
      const { stack } = this.app.router;
      const time = moment();

      const interface_list = await knex(table_name).select('uuid', 'url', 'key').where({ model: 'HISTORY', is_delete: 0 });

      for (const s of stack) {
        const method = s.methods[s.methods.length - 1];
        const key = `${method}${s.path.replace(/\//g, ':')}`;
        const interfaces = interface_list.find(f => {
          return f.key === key;
        });

        if (!interfaces) {
          const obj = {
            uuid: uuidV4().replace(/-/g, ''),
            model: 'HISTORY',
            name: s.name,
            key: `${method}${s.path.replace(/\//g, ':')}`,
            url: s.path,
            method,
            type: 1,
            status: 0,
            parent_id: '-1',
            create_time: moment(time).format('YYYY-MM-DD HH:mm:ss'),
            update_time: moment(time).format('YYYY-MM-DD HH:mm:ss'),
            create_by: '-1',
            update_by: '-1',
            is_delete: 0,
          };

          list.push(obj);
        }
      }


      if (list.length !== 0) {
        await knex(table_name).insert(list);
      }

      return 'success';
    } catch (error) {
      console.log(error);
      throw new Error('service错误');
    }
  }

  async list(name, model, url, reqmethod, type, order, method, pageIndex, pageSize) {
    const { ctx } = this;
    try {
      const sql = ctx.app.knex(`${history_table} as t1`).select(' t1.uuid', 't1.model', 't1.url', 't1.ip', 't1.method', 't1.name',
        't1.param', 't1.result', 't1.type', 't1.create_time', 't1.update_time', 't2.name as create_name', 't3.name as update_time')
        .leftJoin(`${user_table} as t2`, function() {
          this.on('t1.create_by', '=', 't2.uuid');
        })
        .leftJoin(`${user_table} as t3`, function() {
          this.on('t1.update_by', '=', 't3.uuid');
        });


      const count = ctx.app.knex(history_table).count('uuid as count');


      if (name) {
        sql.whereLike('t1.name', `%${name}%`);
        count.whereLike('name', `%${name}%`);
      }

      if (model) {
        sql.andWhereLike('t1.model', `%${model}%`);
        count.andWhereLike('model', `%${model}%`);
      }

      if (url) {
        sql.andWhereLike('t1.url', `%${url}%`);
        count.andWhereLike('url', `%${url}%`);
      }

      if (reqmethod) {
        sql.andWhereLike('t1.method', `%${reqmethod}%`);
        count.andWhereLike('method', `%${reqmethod}%`);
      }

      if (type) {
        sql.andWhere('t1.type', type);
        count.andWhere('type', type);
      }

      const data = await sql.orderBy(order, method).limit(Number(pageSize)).offset(((Number(pageIndex) - 1) * Number(pageSize)));
      const c = await count.first();


      return {
        count: c.count,
        data,
      };
    } catch (error) {
      throw error;
    }
  }

  async insert(model, url, ip, method, param, result, type) {
    const ctx = this.ctx;
    const time = moment();
    try {

      if (!ctx.app.config.smInfo) {
        const data = await this.getSM();
        ctx.app.config.smInfo = data;
      }

      const key = `${method}${url.replace(/\//g, ':')}`;

      const obj = await ctx.app.knex(table_name).select('name').where({ key })
        .first();


      if (typeof param === 'object') {
        param = sm4.encrypt(JSON.stringify(param), ctx.app.config.smInfo.key, { mode: ctx.app.config.smInfo.mode, iv: ctx.app.config.smInfo.iv });
      }


      if (typeof result === 'object') {
        result = sm4.encrypt(JSON.stringify(result), ctx.app.config.smInfo.key, { mode: ctx.app.config.smInfo.mode, iv: ctx.app.config.smInfo.iv });
      }

      const instance = {
        uuid: uuidV4(),
        model, url, ip, method, param, result, type,
        name: obj.name,
        create_time: moment(time).format('YYYY-MM-DD HH:mm:ss'),
        update_time: moment(time).format('YYYY-MM-DD HH:mm:ss'),
        create_by: '-1',
        update_by: '-1',
        is_delete: 0,
      };

      await ctx.app.knex(history_table).insert(instance);

      return true;
    } catch (error) {
      throw error;
    }
  }


  async info(uuid) {
    const ctx = this.ctx;
    try {
      if (!ctx.app.config.smInfo) {
        const data = await this.getSM();
        ctx.app.config.smInfo = data;
      }

      const info = await ctx.app.knex.select('*').from(history_table).where({ uuid })
        .first();

      info.param = JSON.parse(sm4.decrypt(info.param, ctx.app.config.smInfo.key, { mode: ctx.app.config.smInfo.mode, iv: ctx.app.config.smInfo.iv }));
      info.result = JSON.parse(sm4.decrypt(info.result, ctx.app.config.smInfo.key, { mode: ctx.app.config.smInfo.mode, iv: ctx.app.config.smInfo.iv }));


      return info;
    } catch (error) {
      throw error;
    }
  }


  async getSM() {
    const app = this.app;
    try {
      const config = {
        method: app.config.sm.method,
        headers: {},
        baseURL: app.config.sm.baseURL,
        url: app.config.sm.path,
      };

      const data = await this.send(config);

      return data.data.data;
    } catch (error) {
      throw error;
    }
  }


  async send(config) {
    try {


      const data = await axios(config);


      return data;

    } catch (error) {

      // console.log(error);
      throw error;
    }
  }
}

module.exports = HomeService;
